<template>
  <div class="file-preview-container">
    <!-- 文件头部信息 -->
    <div class="preview-header" v-if="showHeader">
      <div class="file-info">
        <i :class="getFileIcon()" class="file-icon"></i>
        <span class="file-name">{{ fileName }}</span>
      </div>
      <div class="file-actions">
        <el-button
          type="primary"
          size="small"
          @click="downloadFile"
          :loading="downloadLoading"
        >
          下载文件
        </el-button>
      </div>
    </div>

    <!-- 预览内容区域 -->
    <div class="preview-content">
      <!-- 加载状态 -->
      <div v-if="loading" class="loading-container">
        <el-loading-spinner size="40" />
        <p>正在加载文件预览...</p>
      </div>

      <!-- 错误状态 -->
      <div v-else-if="error" class="error-container">
        <i class="el-icon-warning-outline error-icon"></i>
        <h3>预览失败</h3>
        <p>{{ errorMessage }}</p>
        <el-button type="primary" @click="retryPreview">重试</el-button>
      </div>

      <!-- 图片预览 -->
      <div v-else-if="isImage" class="image-preview">
        <img
          :src="fileUrl"
          :alt="fileName"
          @load="handleImageLoad"
          @error="handlePreviewError"
          class="preview-image"
        />
      </div>

      <!-- Word文档预览 -->
      <div v-else-if="isWordDoc" class="office-preview">
        <VueOfficeDocx
          :src="fileUrl"
          style="height: 100%"
          @rendered="handleOfficeLoaded"
          @error="handleOfficeError"
        />
      </div>

      <!-- Excel文档预览 -->
      <div v-else-if="isExcelDoc" class="office-preview">
        <VueOfficeExcel
          :src="fileUrl"
          style="height: 100%"
          @rendered="handleOfficeLoaded"
          @error="handleOfficeError"
        />
      </div>

      <!-- PowerPoint文档预览 -->
      <div v-else-if="isPptDoc || isPdf" class="office-preview">
        <VueOfficePdf
          :src="fileUrl"
          style="height: 100%"
          @rendered="handleOfficeLoaded"
          @error="handleOfficeError"
        />
      </div>

      <!-- 不支持的文件类型 -->
      <div v-else class="unsupported-container">
        <i class="el-icon-document unsupported-icon"></i>
        <h3>暂不支持预览此文件类型</h3>
        <p>您可以下载文件到本地查看</p>
        <el-button type="primary" @click="downloadFile">下载文件</el-button>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import {
  ref,
  computed,
  onMounted,
  watch,
  defineProps,
  withDefaults,
} from "vue";
import { ElButton, ElMessage } from "element-plus";
import VueOfficeDocx from "@vue-office/docx";
import VueOfficeExcel from "@vue-office/excel";
import VueOfficePdf from "@vue-office/pdf";

// Props定义
interface Props {
  fileType: string; // 文件类型: 'image' | 'pdf' | 'doc' | 'excel' | 'ppt'
  fileUrl: string; // 文件资源地址
  fileName: string; // 文件名称
  showHeader?: boolean; // 是否显示头部信息，默认true
  height?: string | number; // 预览区域高度，默认'500px'
}

const props = withDefaults(defineProps<Props>(), {
  showHeader: true,
  height: "500px",
});

// 响应式数据
const loading = ref(true);
const error = ref(false);
const errorMessage = ref("");
const downloadLoading = ref(false);

// PDF相关状态
const currentPage = ref(1);
const totalPages = ref(0);
const scale = ref(1.0);

// 计算属性
const isImage = computed(() => {
  return (
    props.fileType === "image" ||
    /\.(jpg|jpeg|png|gif|bmp|webp|svg)$/i.test(props.fileUrl)
  );
});

const isPdf = computed(() => {
  return props.fileType === "pdf" || /\.pdf$/i.test(props.fileUrl);
});

const isWordDoc = computed(() => {
  return props.fileType === "doc" || /\.(doc|docx)$/i.test(props.fileUrl);
});

const isExcelDoc = computed(() => {
  return props.fileType === "excel" || /\.(xls|xlsx)$/i.test(props.fileUrl);
});

const isPptDoc = computed(() => {
  return props.fileType === "ppt" || /\.(ppt|pptx)$/i.test(props.fileUrl);
});

// 获取文件图标
const getFileIcon = () => {
  const iconMap: Record<string, string> = {
    image: "el-icon-picture-outline",
    pdf: "el-icon-document",
    doc: "el-icon-document",
    excel: "el-icon-s-grid",
    ppt: "el-icon-video-play",
  };

  if (isImage.value) return "el-icon-picture-outline";
  if (isPdf.value) return "el-icon-document";
  if (isWordDoc.value) return "el-icon-document";
  if (isExcelDoc.value) return "el-icon-s-grid";
  if (isPptDoc.value) return "el-icon-video-play";

  return iconMap[props.fileType] || "el-icon-document";
};

// 处理图片加载成功
const handleImageLoad = () => {
  loading.value = false;
  error.value = false;
};

// 处理PDF加载成功
const handlePdfLoaded = (pdf: any) => {
  loading.value = false;
  error.value = false;
  totalPages.value = pdf.numPages;
  currentPage.value = 1;
};

// 处理PDF加载错误
const handlePdfError = (err: any) => {
  loading.value = false;
  error.value = true;
  errorMessage.value = "PDF文件加载失败，请检查文件地址是否正确";
  console.error("PDF加载错误:", err);
};

// 处理Office文档加载成功
const handleOfficeLoaded = () => {
  loading.value = false;
  error.value = false;
};

// 处理Office文档加载错误
const handleOfficeError = (err: any) => {
  loading.value = false;
  error.value = true;
  errorMessage.value = "Office文档加载失败，请检查文件地址是否正确";
  console.error("Office文档加载错误:", err);
};

// 处理预览错误
const handlePreviewError = () => {
  loading.value = false;
  error.value = true;
  errorMessage.value = "文件加载失败，请检查文件地址是否正确或网络连接是否正常";
};

// 处理PDF内部链接点击
const handleInternalLink = (destination: any) => {
  // 处理PDF内部链接跳转
  console.log("PDF内部链接:", destination);
};

// 重试预览
const retryPreview = () => {
  loading.value = true;
  error.value = false;
  errorMessage.value = "";

  // 重置PDF状态
  currentPage.value = 1;
  totalPages.value = 0;
  scale.value = 1.0;

  // 重新触发预览逻辑
  setTimeout(() => {
    if (isImage.value) {
      // 重新加载图片
      const img = new Image();
      img.onload = handleImageLoad;
      img.onerror = handlePreviewError;
      img.src = props.fileUrl;
    } else {
      // 其他类型直接设置加载完成
      loading.value = false;
    }
  }, 500);
};

// 下载文件
const downloadFile = async () => {
  try {
    downloadLoading.value = true;

    // 创建下载链接
    const link = document.createElement("a");
    link.href = props.fileUrl;
    link.download = props.fileName;
    link.target = "_blank";

    // 触发下载
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);

    ElMessage.success("开始下载文件");
  } catch (err) {
    ElMessage.error("下载失败，请重试");
  } finally {
    downloadLoading.value = false;
  }
};

// 初始化预览
const initPreview = () => {
  loading.value = true;
  error.value = false;

  // 重置PDF状态
  currentPage.value = 1;
  totalPages.value = 0;
  scale.value = 1.0;

  if (isImage.value) {
    // 预加载图片
    const img = new Image();
    img.onload = handleImageLoad;
    img.onerror = handlePreviewError;
    img.src = props.fileUrl;
  } else {
    // 其他类型由组件自己处理加载状态
    setTimeout(() => {
      if (loading.value) {
        // 如果2秒后还在加载，则认为可能有问题
        loading.value = false;
      }
    }, 2000);
  }
};

// 监听文件URL变化
watch(
  () => props.fileUrl,
  () => {
    if (props.fileUrl) {
      initPreview();
    }
  },
  { immediate: true }
);

// 组件挂载时初始化
onMounted(() => {
  if (props.fileUrl) {
    initPreview();
  }
});
</script>

<style lang="scss" scoped>
.file-preview-container {
  width: 100%;
  border: 1px solid #e4e7ed;
  border-radius: 8px;
  background: #fff;
  overflow: hidden;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);

  .preview-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 16px 20px;
    background: #fafafa;
    border-bottom: 1px solid #e4e7ed;

    .file-info {
      display: flex;
      align-items: center;
      flex: 1;

      .file-icon {
        font-size: 20px;
        color: #409eff;
        margin-right: 8px;
      }

      .file-name {
        font-size: 14px;
        font-weight: 500;
        color: #303133;
        word-break: break-all;
      }
    }

    .file-actions {
      margin-left: 16px;
    }
  }

  .preview-content {
    position: relative;
    min-height: v-bind('typeof height === "number" ? height + "px" : height');
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;

    .loading-container {
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      height: 200px;
      color: #909399;

      p {
        margin-top: 16px;
        font-size: 14px;
      }
    }

    .error-container {
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      height: 300px;
      text-align: center;

      .error-icon {
        font-size: 48px;
        color: #f56c6c;
        margin-bottom: 16px;
      }

      h3 {
        margin: 0 0 8px 0;
        font-size: 18px;
        color: #303133;
      }

      p {
        margin: 0 0 20px 0;
        font-size: 14px;
        color: #909399;
      }
    }

    .image-preview {
      width: 100%;
      height: 100%;
      display: flex;
      align-items: center;
      justify-content: center;
      padding: 20px;

      .preview-image {
        max-width: 100%;
        max-height: 100%;
        object-fit: contain;
        border-radius: 4px;
        box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
      }
    }

    .pdf-preview {
      width: 100%;
      height: v-bind('typeof height === "number" ? height + "px" : height');
      display: flex;
      flex-direction: column;

      .pdf-viewer {
        flex: 1;
        width: 100%;
        overflow: auto;
        background: #f5f5f5;
      }

      .pdf-controls {
        display: flex;
        justify-content: space-between;
        align-items: center;
        padding: 12px 16px;
        background: #fafafa;
        border-top: 1px solid #e4e7ed;

        .page-controls {
          display: flex;
          align-items: center;
          gap: 8px;

          .page-info {
            font-size: 14px;
            color: #606266;
            margin: 0 8px;
          }
        }

        .zoom-controls {
          display: flex;
          align-items: center;
          gap: 8px;

          .zoom-info {
            font-size: 14px;
            color: #606266;
            margin: 0 8px;
            min-width: 40px;
            text-align: center;
          }
        }
      }
    }

    .office-preview {
      width: 100%;
      height: v-bind('typeof height === "number" ? height + "px" : height');
      padding: 20px;
      box-sizing: border-box;
      overflow: auto;
    }

    .unsupported-container {
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      height: 300px;
      text-align: center;

      .unsupported-icon {
        font-size: 48px;
        color: #909399;
        margin-bottom: 16px;
      }

      h3 {
        margin: 0 0 8px 0;
        font-size: 18px;
        color: #303133;
      }

      p {
        margin: 0 0 20px 0;
        font-size: 14px;
        color: #909399;
      }
    }
  }
}

// 响应式设计
@media (max-width: 768px) {
  .file-preview-container {
    .preview-header {
      flex-direction: column;
      align-items: flex-start;
      gap: 12px;

      .file-actions {
        margin-left: 0;
        width: 100%;
      }
    }

    .preview-content {
      .image-preview {
        padding: 10px;
      }

      .office-preview {
        padding: 10px;
      }

      .pdf-preview {
        .pdf-controls {
          flex-direction: column;
          gap: 12px;
        }
      }
    }
  }
}
</style>
